﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Application
{
    using System;
    using System.Diagnostics.CodeAnalysis;

    /// <summary>Represents a connection to a network of a given host.</summary>
    internal sealed class NetworkConnection : IDisposable
    {
        private IntPtr connection;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>See <see cref="IDisposable.Dispose"/>.</summary>
        public void Dispose()
        {
            this.PrivateDispose();
            GC.SuppressFinalize(this);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal NetworkConnection(string hostName, uint timeoutMilliseconds)
        {
            // Although the connection manager makes a connection at the transport level, it seems to insist on the
            // protocol prefix.
            Guid destination;
            NativeMethods.ConnMgrMapURL("http://" + hostName, out destination, 0);
            NetworkConnectionStatus status;

            if (NativeMethods.ConnMgrEstablishConnectionSync(
                new NativeMethods.CONNMGR_CONNECTIONINFO(NativeMethods.CONNMGR_FLAG_PROXY.NONE, destination),
                out this.connection,
                timeoutMilliseconds,
                out status) != 0)
            {
                throw new NetworkConnectionFailedException(status);
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        ~NetworkConnection()
        {
            this.PrivateDispose();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void PrivateDispose()
        {
            if (this.connection != IntPtr.Zero)
            {
                NativeMethods.ConnMgrReleaseConnection(this.connection, 30);
                this.connection = IntPtr.Zero;
            }
        }
    }
}
